/* 
 * Enterprise Library Extensions - DI + ORM.
 * Copyright (C) 2006
 *
 * GNU General Public License
 *
 * This program is free software; you can redistribute 
 * it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using ELE.Common.Util;
using ELE.EnterpriseLibrary.Naming.Spi;
using ELE.EnterpriseLibrary.Naming.Configuration;
using ELE.EnterpriseLibrary.Naming.Factories;
using ELE.EnterpriseLibrary.Common.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace ELE.EnterpriseLibrary.Naming
{
  /// <summary>
  /// This class is the starting context for performing naming operations. 
  /// <br/>All naming operations are relative to a context. The initial context implements the Context interface and provides the starting point for resolution of names. 
  /// <br/><br/>When the initial context is constructed, its environment is initialized with properties defined in the environment parameter passed to the constructor, and in any application resource files. In addition, a small number of standard ONDi properties may be specified as system properties or as applet parameters (through the use of Context.APPLET). These special properties are listed in the field detail sections of the Context and LdapContext interface documentation. 
  /// <br/><br/>ONDI determines each property's value by merging the values from the following two sources, in order: 
  /// <br/>The first occurrence of the property from the constructor's environment parameter and (for appropriate properties) the applet parameters and system properties. 
  /// <br/>The application resource files (ondi.properties). 
  /// <br/>For each property found in both of these two sources, or in more than one application resource file, the property's value is determined as follows. If the property is one of the standard ONDi properties that specify a list of ONDi factories (see Context), all of the values are concatenated into a single colon-separated list. For other properties, only the first value found is used. 
  /// <br/> initial context implementation is determined at runtime. The default policy uses the environment property "ele.naming.factory.initial", which contains the class name of the initial context factory. An exception to this policy is made when resolving URL strings, as described below. 
  /// <br/><br/>When a URL string (a String of the form scheme_id:rest_of_name) is passed as a name parameter to any method, a URL context factory for handling that scheme is located and used to resolve the URL. If no such factory is found, the initial context specified by "ele.naming.factory.initial" is used. Similarly, when a CompositeName object whose first component is a URL string is passed as a name parameter to any method, a URL context factory is located and used to resolve the first name component. See NamingManager.getURLContext() for a description of how URL context factories are located. 
  /// <br/><br/>This default policy of locating the initial context and URL context factories may be overridden by calling NamingManager.setInitialContextFactoryBuilder(). 
  /// <br/><br/>NoInitialContextException is thrown when an initial context cannot be instantiated. This exception can be thrown during any interaction with the InitialContext, not only when the InitialContext is constructed. For example, the implementation of the initial context might lazily retrieve the context only when actual methods are invoked on it. The application should not have any dependency on when the existence of an initial context is determined. 
  /// <br/><br/>When the environment property "ele.naming.factory.initial" is non-null, the InitialContext constructor will attempt to create the initial context specified therein. At that time, the initial context factory involved might throw an exception if a problem is encountered. However, it is provider implementation-dependent when it verifies and indicates to the users of the initial context any environment property- or connection- related problems. It can do so lazily--delaying until an operation is performed on the context, or eagerly, at the time the context is constructed. 
  /// <br/><br/>An InitialContext instance is not synchronized against concurrent access by multiple threads. Multiple threads each manipulating a different InitialContext instance need not synchronize. Threads that need to access a single InitialContext instance concurrently should synchronize amongst themselves and provide the necessary locking. 
	/// </summary>
	public class InitialContext : NamingContextConstants, INamingContext, IDisposable
  {
    private static object s_mutex = new object();
    private object m_mutex = new object();
    private LogWriter mLogger = null;
    /// <summary>
    /// The log writer
    /// </summary>
    public LogWriter Logger
    {
      get { return mLogger; }
    }
    /// <summary>
    /// The static initial context
    /// </summary>
    protected static InitialContext sInitialContext;
    /// <summary>
    /// A list of registered names for remote objects
    /// </summary>
    protected Hashtable mRegisteredRemotingServices;
    /// <summary>
    /// public accessor for registered remote services
    /// </summary>
    public Hashtable RegisteredRemoteServices
    {
      get { return mRegisteredRemotingServices; }
    }
    private Hashtable mUnresolvedReferences;
    /// <summary>
    /// Circular reference holder
    /// </summary>
    public Hashtable UnresolvedReferences
    {
      get { return mUnresolvedReferences; }
    }
    /// <summary>
    /// Adds a reference to be resolved at a later time
    /// </summary>
    /// <param name="pName"></param>
    /// <param name="pReference"></param>
    public void AddUnresolvedReference(string pName, string pReference)
    {
      if(mUnresolvedReferences == null)
      {
        mUnresolvedReferences = new Hashtable();
      }
      mUnresolvedReferences.Add(pName, pReference);
    }
    /// <summary>
    /// Removes all references related to a named component that failed initialization
    /// </summary>
    /// <param name="pName"></param>
    public void RemoveUnresolvedReferencesForNamedObject(string pName)
    {
      if(mUnresolvedReferences != null)
      {
        ArrayList keysToRemove = new ArrayList();
        foreach(string key in mUnresolvedReferences.Keys)
        {
          if(StringUtils.Contains(key, pName))
          {
            keysToRemove.Add(key);
          }
          else
          {
            string keyval = (string)mUnresolvedReferences[key];
            if(StringUtils.Contains(keyval, pName))
            {
              keysToRemove.Add(key);
            }
          }
        }
        foreach(string key in keysToRemove)
        {
          this.Log(String.Format("Removing key {0} from unresolved references list because either the key or the value match a reference to invalid object named {1}",key, pName), null, LogLevel.Debug);
          mUnresolvedReferences.Remove(key);
        }
      }
    }
    private StringCollection mInProcessComponents;
    /// <summary>
    /// Adds a reference to be resolved at a later time
    /// </summary>
    /// <param name="pName"></param>
    public bool IsInProcess(string pName)
    {
      if(mInProcessComponents == null || !mInProcessComponents.Contains(pName))
      {
        return false;
      }
      return true;
    }
    /// <summary>
    /// In process stack of names
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public bool AddToInProcess(string name)
    {
      //this.Log("InitialContext: Adding to in process object named " + name, null, ELE.EnterpriseLibrary.Logging.LogLevel.Debug);
      if (mInProcessComponents == null)
      {
        mInProcessComponents = new StringCollection();
      }
      if (mInProcessComponents.Contains(name))
      {
        //this.Log("InitialContext: Object named " + name + " is already in list skipping circular reference", null, ELE.EnterpriseLibrary.Logging.LogLevel.Warn);
        return false;
      }
      mInProcessComponents.Add(name);
      return true;
    }
    /// <summary>
    /// removes a name from the in-process stack
    /// </summary>
    /// <param name="name"></param>
    public void RemoveFromInProcess(string name)
    {
      //this.Log("NamingManager: Removing from in process object named " + name, null, ELE.EnterpriseLibrary.Logging.LogLevel.Debug);
      if (mInProcessComponents != null)
      {
        mInProcessComponents.Remove(name);
      }
    }
    private void ResolveRemainingReferences()
    {
      if(mUnresolvedReferences != null && mUnresolvedReferences.Count > 0)
      {
        StringCollection resolved = new StringCollection();

        foreach(string name in this.mUnresolvedReferences.Keys)
        {
          string val = (string) this.mUnresolvedReferences[name];
          try
          {
            //this.Log("Attempting to resolve circular reference ", null, LogLevel.Information);
            ComponentInitializer ci = new ComponentInitializer(name, val, ComponentInitializer.TYPE_REF);
            object obj = ComponentObjectFactory.GetReferencedObjectFromComponentInitializer(ci, this);
            string compName = StringUtils.ExtractFromDelimiters(name, GenericConfiguration.ESCAPE_INDEX_START, GenericConfiguration.ESCAPE_INDEX_END);
            string propertyName = name.Substring(name.LastIndexOf(GenericConfiguration.ESCAPE_INDEX_END) + 1);
            object destObj = this.Lookup(compName);
            if(destObj != null)
            {
              System.Reflection.PropertyInfo prop = destObj.GetType().GetProperty(propertyName);
              if(prop != null)
              {
                this.Log("Setting property " + propertyName + " on " + compName, null, LogLevel.Debug);
                prop.SetValue(destObj, obj, null);
              }
            }
          }
          catch(CircularReferenceException)
          {
            //Not ready so ignore and try again later
            continue;
          }
          catch(Exception e)
          {
            this.Log("Exception attempting to resolve circular reference", e, LogLevel.Error);
          }
          resolved.Add(name);
        }
        foreach(string name in resolved)
        {
          this.mUnresolvedReferences.Remove(name);
        }
      }
    }
    /// <summary>
    /// A stack holding exceptions
    /// </summary>
    protected IList mExceptionStack;
    /// <summary>
    /// Add an exception to the stack
    /// </summary>
    /// <param name="pExc">the exception</param>
    public void AddException(Exception pExc)
    {
      if(mExceptionStack == null) mExceptionStack = new ArrayList();
      mExceptionStack.Add(pExc);
    }
    /// <summary>
    /// Empty the stack
    /// </summary>
    public void ClearExceptionStack()
    {
      mExceptionStack = null;
    }
    /// <summary>
    /// Returns the list of exceptions if any or null if none
    /// </summary>
    public IList Exceptions
    {
      get { return mExceptionStack; }
    }
    /// <summary>
    /// Field holding the result of calling NamingManager.GetInitialContext(). 
    /// </summary>
    protected  INamingContext defaultInitCtx;
    /// <summary>
    /// Public accessor to the default context
    /// </summary>
    public INamingContext DefaultContext
    {
      get
      {
        return defaultInitCtx;
      }
    }
    /// <summary>
    /// Gets a remote link name from the environment settings of this context
    /// Specifically looks at RemotePort, RemoteUrl and RemoteProtocol
    /// </summary>
    public string RemoteLinkName
    {
      get
      {
        if(Environment[REMOTE_PORT] != null && Environment[REMOTE_URL] != null)
        {
          if(Environment[REMOTE_PROTOCOL] == null)
          {
            Environment.Add(REMOTE_PROTOCOL, REMOTING_PROTOCOL_TCP);
          }
          System.Text.StringBuilder linkName = new System.Text.StringBuilder();
          linkName.Append(Environment[REMOTE_PROTOCOL]).Append(CompositeNameParser.SECTION_DELIMITER);
          linkName.Append(CompositeNameParser.NAME_DELIMITER).Append(CompositeNameParser.NAME_DELIMITER);
          linkName.Append(Environment[REMOTE_URL]).Append(CompositeNameParser.SECTION_DELIMITER);
          linkName.Append(Environment[REMOTE_PORT]);
          return linkName.ToString();
        }
        return null;
      }
    }
    /// <summary>
    /// Gets a link name to this context's remoting settings from the environment settings of this context
    /// Specifically looks at RemotingPort and RemotingProtocol
    /// </summary>
    public string RemotingLinkName
    {
      get
      {
        if (Environment[REMOTING_PORT] != null)
        {
          if (Environment[REMOTING_PROTOCOL] == null)
          {
            Environment.Add(REMOTING_PROTOCOL, REMOTING_PROTOCOL_TCP);
          }
          System.Text.StringBuilder linkName = new System.Text.StringBuilder();
          linkName.Append(Environment[REMOTING_PROTOCOL]).Append(CompositeNameParser.SECTION_DELIMITER);
          linkName.Append(CompositeNameParser.NAME_DELIMITER).Append(CompositeNameParser.NAME_DELIMITER);
          linkName.Append("localhost").Append(CompositeNameParser.SECTION_DELIMITER);
          linkName.Append(Environment[REMOTING_PORT]);
          return linkName.ToString();
        }
        return null;
      }
    }
    /// <summary>
    /// Gets the url of the remote monitor object defined by the remote settings of this context
    /// </summary>
    public string RemoteContextMonitorUrl
    {
      get
      {
        return RemoteLinkName + CompositeNameParser.NAME_DELIMITER + CONTEXT_REMOTING_MONITOR_NAME;
      }
    }
    private IChannelSender mClientChannel;
    /// <summary>
    /// The channel on which the context sends messages to remote contexts
    /// </summary>
    public IChannelSender RemotingClientChannel
    {
      get
      {
        return mClientChannel;
      }
    }
    private IChannelReceiver mServerChannel;
    /// <summary>
    /// The channel on which the context receives messages from remote contexts and to which serves its remote objects
    /// </summary>
    public IChannelReceiver RemotingServerChannel
    {
      get
      {
        return mServerChannel;
      }
    }
    /// <summary>
    /// Field indicating whether the initial context has been obtained by calling 
    /// NamingManager.GetInitialContext().
    /// </summary>
    protected  bool gotDefault = false;  
    /// <summary>
    /// The environment associated with this InitialContext. 
    /// </summary>
    protected  Hashtable myProps; 
    /// <summary>
    /// Objects bound to this initial context directly
    /// </summary>
    protected BindingTable myBindingTable;
    /// <summary>
    /// COntexts contained within this context to look for objects
    /// </summary>
    protected ContextTable mySubContexts;
    /// <summary>
    /// 
    /// </summary>
    protected string mInitialConfigurationFile = NamingContextConstants.DEFAULT_INITIAL_FILE;
    /// <summary>
    /// Public accessor for the location of the configuration file for this initial context
    /// </summary>
    public string InitialConfigurationFile
    {
      get { return mInitialConfigurationFile;}
    }
    /// <summary>
    /// This is the name used in the app.config or web.config to locate the initial context setup file
    /// </summary>
    public const string CONTEXT_SETTINGS_KEY_NAME = "ELE.EnterpriseLibrary.Naming.InitialContext";
    /// <summary>
    /// Name of the service that provides remoting monitoring tool
    /// </summary>
    public const string CONTEXT_REMOTING_MONITOR_NAME = "ELE/Remoting/Context/Monitor";
    /// <summary>
    /// Name of the context bound object that can be used by other context components to locate remote objects
    /// </summary>
    public const string CONTEXT_REMOTE_LOOKUP_MANAGER_NAME = "ELE/Remote/Context/Manager";
    /// <summary>
    /// Constructs an initial context. 
    /// </summary>
    public InitialContext() : this(false) 
    {
    }
    /// <summary>
    /// Constructs an initial context with the option of not initializing it.
    /// </summary>
    /// <param name="lazy">Initialize or not</param>
    protected  InitialContext(bool lazy) 
    {
      if(!lazy)
      {
        Init();
      }
    } 
    /// <summary>
    /// Constructs an initial context using the supplied environment. 
    /// </summary>
    /// <param name="environment">Environment settings</param>
    public InitialContext(Hashtable environment)
    {
      myProps = environment;
      Init();
    }
    /// <summary>
    /// A customized Initial context from a config file
    /// </summary>
    /// <param name="confFile"></param>
    public InitialContext(string confFile)
    {
      Init(confFile);
    }
    /// <summary>
    /// Release resources
    /// </summary>
    ~InitialContext()
    {
      this.Dispose(false);
    }
    /// <summary>
    /// Reload the context 
    /// </summary>
    public static void Reload()
    {
      string configFile = sInitialConfigurationFile;
      Unload();
      StaticInit(sInitialConfigurationFile);
    }
    /// <summary>
    /// Unload the context
    /// </summary>
    public static void Unload()
    {
      sInitialContext.Dispose();
      sInitialContext = null;
    }
    /// <summary>
    /// Initialize the context
    /// </summary>
    protected void Init()
    {
      string appConfig = System.Configuration.ConfigurationManager.AppSettings[CONTEXT_SETTINGS_KEY_NAME];
      Init(appConfig);
    }
    /// <summary>
    /// Initializes based on a given config file
    /// </summary>
    /// <param name="confFile"></param>
    protected void Init(string confFile)
    {
      this.ClearExceptionStack();
      if(myProps == null)
      {
        try
        {
          mInitialConfigurationFile = confFile;
          ContextConfiguration config = ContextConfigurationParser.ParseContextConfiguration(mInitialConfigurationFile);
          
          if(config != null)
          {
            config.ResolveReferences();
            //SET the root of the context if provided, if not assume the directory where the config file is
            this.AddToEnvironment(NamingContextConstants.LOCAL_CONTEXT_ROOT, config.RootDirectory);
            
            if(config.Environment != null)
            {
              foreach(string key in config.Environment.Keys)
              {
                this.AddToEnvironment(key, config.Environment[key]);
              }
            }
            
            // If a log is provided set it up.
            if (config.LoggerConfigurationFile != null)
            {
              this.AddToEnvironment(NamingContextConstants.LOCAL_CONTEXT_LOGGER, config.LoggerConfigurationFile);
              try
              {
                FileConfigurationSource fcs = new FileConfigurationSource(config.LoggerConfigurationFile);
                LogWriterFactory lwf = new LogWriterFactory(fcs);
                mLogger = lwf.Create();
                LogEntry entry = new LogEntry();
                entry.Message = "Initialized logger on InitialContext";
                entry.Categories = new List<string>();
                entry.Categories.Add(LoggingObjectBase.GetLevelCategoryName(LogLevel.Information));
                entry.TimeStamp = DateTime.Now;
                mLogger.Write(entry);
              }
              catch (Exception logExcep)
              {
                this.AddException(logExcep);
              }
            }
            // Add global entries if any
            if(config.GlobalEntries != null)
            {
              this.AddToEnvironment(NamingContextConstants.LOCAL_GLOBAL_ENTRIES, config.GlobalEntries);
            }
            //Add  subcontexts
            if (config.SubContexts != null && config.SubContexts.Count > 0)
            {
              this.AddToEnvironment(NamingContextConstants.SUB_CONTEXTS, config.SubContexts);
            }
            if (this.Environment == null || this.Environment[NamingContextConstants.OBJECT_FACTORIES] == null)
            {
              IList factories = new ArrayList();
              //By default use the default object factory if not specified.
              factories.Add(new ClassAssemblyPair("ELE.EnterpriseLibrary.Naming.Factories.DefaultNamingObjectFactory"));
              this.AddToEnvironment(NamingContextConstants.OBJECT_FACTORIES, factories);
            }
            if (this.Environment == null || this.Environment[NamingContextConstants.INITIAL_CONTEXT_FACTORY] == null)
            {
              IList factories = new ArrayList();
              //By default use the default ctx factory if not specified.
              this.AddToEnvironment(NamingContextConstants.INITIAL_CONTEXT_FACTORY, new ClassAssemblyPair("ELE.EnterpriseLibrary.Naming.Factories.DefaultNamingContextFactory"));
            }
          }

        }
        catch(Exception e)
        {
          this.AddException(e);
        }
      }
      try
      {
        // *********************
        // SETUP sub contexts
        // *********************        
        if(myProps[NamingContextConstants.SUB_CONTEXTS] != null)
        {
          
          foreach(string subCtxKey in ((Hashtable)myProps[NamingContextConstants.SUB_CONTEXTS]).Keys)
          {
            object subCtx = ((Hashtable)myProps[NamingContextConstants.SUB_CONTEXTS])[subCtxKey];
            INamingContext ctx = null;
            if (subCtx is string)
            {
              Hashtable initialParam = new Hashtable();
              initialParam.Add(NamingContextConstants.INITIAL_CONTEXT_FACTORY, myProps[NamingContextConstants.INITIAL_CONTEXT_FACTORY]);
              initialParam.Add(NamingContextConstants.INITIAL_CONTEXT_FACTORY_ASSEMBLY, myProps[NamingContextConstants.INITIAL_CONTEXT_FACTORY_ASSEMBLY]);

              string ctxConfFile = (string)ContextValueParser.GetStringDefinedObject(myProps, null, (string)subCtx, "".GetType());
              initialParam.Add(CONTEXT_SETTINGS_KEY_NAME, ctxConfFile);
              try
              {
                ctx = NamingManager.GetInitialContext(initialParam);
                if (ctx != null)
                {
                  if (this.mySubContexts == null)
                  {
                    this.mySubContexts = new ContextTable();
                  }
                  this.mySubContexts.Add(subCtxKey, ctx);
                  this.Log("Successfull initialization of subcontext named " + subCtxKey + ", using config file " + ctxConfFile,null,LogLevel.Debug);
                }
                else
                {
                  this.Log("Error initializing subcontext named " + subCtxKey + " make sure the configuration points to the correct path",null,LogLevel.Warning);
                }
              }
              catch(Exception subCtxExcep)
              {
                this.Log("Error initializing subcontext named " + subCtxKey + " the exception is : ",subCtxExcep,LogLevel.Error);
                this.AddException(subCtxExcep);
              }

            }
            else if(subCtx is ComponentInitializer)
            {
              ComponentInitializer ci = (ComponentInitializer) subCtx;
              ctx = this.CreateSubcontext((string)ci.Value);
            }
            if (ctx != null && subCtxKey.ToLower().Equals(ContextConfiguration.TAGNAME_INITIAL.ToLower()))
            {
              this.defaultInitCtx = ctx;
            }
          }
        }
        // *********************
        // SETUP for remoting
        // *********************        
        bool isRemoting = false;
        if(myProps[REMOTING_PORT] != null)
        {
          try
          {
            if(!myProps.ContainsKey(REMOTING_PROTOCOL))
            {
              myProps.Add(REMOTING_PROTOCOL, REMOTING_PROTOCOL_TCP);
            }
            if(StringUtils.CompareToIgnoreCase((string)myProps[REMOTING_PROTOCOL], REMOTING_PROTOCOL_TCP) == 0)
            { 
              BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
              serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
              BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
              
              IDictionary props = new Hashtable();
              props["port"] = myProps[REMOTING_PORT];
              
              if(this.Environment[REMOTING_CHANNEL_NAME] != null)
              {
                props["name"] = (string)this.Environment[REMOTING_CHANNEL_NAME];
              }
              mServerChannel = new TcpChannel(props, clientProv, serverProv);
              ChannelServices.RegisterChannel(mServerChannel, true);
              isRemoting = true;
              Log("Successfull setup of Remoting SERVER on initial context [Port = " + myProps[REMOTING_PORT] + ", channelName = " + myProps[REMOTING_CHANNEL_NAME] + ", type " + myProps[REMOTING_PROTOCOL],null,LogLevel.Debug);
            }
            else
            {
              Log("Only tcp protocol is supported for remoting at this point, could not create " + myProps[REMOTING_PROTOCOL] + " remoting not running",null,LogLevel.Warning);
            }
          }
          catch(Exception remotingExcep)
          {
            Log("Encountered an error while setting up remoting on port " + myProps[REMOTING_PORT] + " thru channel of type " + myProps[REMOTING_PROTOCOL] + "]",remotingExcep,LogLevel.Warning);
            this.AddException(remotingExcep);
          }
        }
        else if(myProps[REMOTING_CONFIGURATION] != null)
        {
          // *********************
          // SETUP for remoting from config files
          // ********************* 
          try
          {
            RemotingConfiguration.Configure((string)myProps[REMOTING_CONFIGURATION], true);
            isRemoting = true;
            Log("Successfull setup of Remoting SERVER on initial context [configuration file = " + (string)myProps[REMOTING_CONFIGURATION] + "]",null,LogLevel.Debug);
          }
          catch(Exception rConfEx)
          {
            Log("Failed to configure remoting from configuration file : " + myProps[REMOTING_CONFIGURATION], rConfEx, LogLevel.Warning);
            this.AddException(rConfEx);
          }
        }
        if (isRemoting)
        {
          //Temporarely open a client connection to initialize remote objects
          IChannelSender clientChannel = null;
          try
          {

            BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
            serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
            BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

            IDictionary props = new Hashtable();

            props["port"] = 0;
            props["name"] = "TemporaryRemotingContextClient";

            clientChannel = new TcpChannel(props, clientProv, serverProv);
            this.Log("Registered temporary remoting client to initialize remote objects.", null, LogLevel.Debug);
            ChannelServices.RegisterChannel(clientChannel, true);

            DirectoryInfo dir = new DirectoryInfo((string)myProps[LOCAL_CONTEXT_ROOT]);
            this.RegisterRemoteComponents(dir);
            if (mRegisteredRemotingServices != null)
            {
              RegisterRemotingContextMonitor();
            }
            Log("Successfully registered remote objects from context ", null, LogLevel.Debug);
          }
          catch (Exception remotingSetupException)
          {
            Log("Failed to configure remoting from configuration when attempting to register remote objects ", remotingSetupException, LogLevel.Warning);
            this.AddException(remotingSetupException);
          }
          finally
          {
            //Close the client connection no matter what.
            if (clientChannel != null)
            {
              ChannelServices.UnregisterChannel(clientChannel);
              this.Log("Un-Registered temporary remoting client after initializing remote objects.", null, LogLevel.Debug);
            }
            clientChannel = null;
          }
        }
        // *********************
        // SETUP for remote listener
        // *********************  
        if(myProps[REMOTE_URL] != null && myProps[REMOTE_PORT] != null)
        {
          try
          {
            
            BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
            serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
            BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

            IDictionary props = new Hashtable();

            props["port"] = 0;
              
            if(this.Environment[REMOTE_CHANNEL_NAME] != null)
            {
              props["name"] = (string)this.Environment[REMOTE_CHANNEL_NAME];
            }

            mClientChannel = new TcpChannel(props, clientProv, serverProv);

            ChannelServices.RegisterChannel(mClientChannel, true);
            RemoteContextManager rcm = new RemoteContextManager();
            rcm.Port = (string)myProps[REMOTE_PORT];
            rcm.Host = (string)myProps[REMOTE_URL];
            rcm.Protocol = (string)myProps[REMOTE_PROTOCOL];
            rcm.ConfigRootDir = this.ContextRootDirectory;
            rcm.Context = this;
            
            rcm.Logger = this.Logger;
            this.Bind(CONTEXT_REMOTE_LOOKUP_MANAGER_NAME,rcm);
            Log("Successfull setup of Remoting CLIENT on initial context [Port = " + myProps[REMOTE_PORT] + ", channelName = " + myProps[REMOTE_CHANNEL_NAME] + ", type " + myProps[REMOTE_PROTOCOL] + "]",null,LogLevel.Debug);
          }
          catch(Exception remoteExcep)
          {
            mClientChannel = null;
            Log("Encountered an error while setting up remoting client for " + myProps[REMOTE_PORT] + " thru channel of type " + myProps[REMOTE_PROTOCOL], remoteExcep, LogLevel.Warning);
            this.AddException(remoteExcep);
          }
        } 
        else if(myProps[REMOTE_CONFIGURATION] != null)
        {
          // *********************
          // SETUP for remoting from config files
          // ********************* 
          try
          {
            RemotingConfiguration.Configure((string)myProps[REMOTE_CONFIGURATION], true);
          }
          catch(Exception rConfEx)
          {
            Log("Failed to configure remote listeners from configuration file : " + myProps[REMOTE_CONFIGURATION], rConfEx, LogLevel.Warning);
            this.AddException(rConfEx);
          }
        }

      }
      catch(Exception ex)
      {
        this.AddException(ex);
      }
      if(this.defaultInitCtx != null)
      {
        gotDefault = true;
      }
    }
    /// <summary>
    /// The static context object that holds initial context settings
    /// </summary>
    /// <value></value>
    public static InitialContext StaticContext
    {
      get
      {
        StaticInit();
        return sInitialContext;
      }
    }
    /// <summary>
    /// The static context's global entries if any
    /// </summary>
    /// <value></value>
    public static Hashtable GlobalEntries
    {
      get
      {
        return (Hashtable)StaticContext.Environment[NamingContextConstants.LOCAL_GLOBAL_ENTRIES];
      }
    }
    /// <summary>
    /// The context's global entries if any
    /// </summary>
    /// <value></value>
    public Hashtable ContextGlobalEntries
    {
      get
      {
        return (Hashtable)Environment[NamingContextConstants.LOCAL_GLOBAL_ENTRIES];
      }
    }
    /// <summary>
    /// The static context object that holds initial context settings
    /// </summary>
    /// <value></value>
    public void Log(string message, Exception exception, LogLevel logLevel)
    {

      if (this.mLogger != null)
      {
        LogEntry entry = new LogEntry();
        entry.Message = message != null ? message : string.Empty;
        entry.Categories = new List<string>();
        entry.Categories.Add(LoggingObjectBase.GetLevelCategoryName(logLevel));
        entry.Win32ThreadId = System.Threading.Thread.CurrentThread.Name;
        entry.TimeStamp = System.DateTime.Now;
        if (exception != null)
        {
          entry.Message += "; " + System.Environment.NewLine + "\tException: " + exception.Message +
                        System.Environment.NewLine + "\tStacktrace: " + exception.StackTrace;
        }
        this.mLogger.Write(entry);
      }
    }
    private static string sInitialConfigurationFile = null;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="initFile"></param>
    public static void StaticInit(string initFile)
    {
      sInitialConfigurationFile = initFile;
      StaticInit();
    }
    /// <summary>
    /// Static initializer that reads from app or web config file
    /// </summary>
    public static void StaticInit()
    {
      
      //First make sure we have a static context setup
      if (sInitialContext == null) 
      {
        lock (s_mutex) 
        {
          // Check once more, just in case someone else just got
          // done creating it...
          if (sInitialContext == null) 
          {
            try 
            {
              if(sInitialConfigurationFile == null)
              {
                sInitialContext = new InitialContext();   
              }
              else
              {
                sInitialContext = new InitialContext(sInitialConfigurationFile);  
              }
                        
            } 
            catch (Exception e) 
            {
              throw e;
            }
          }
        }
      }
    }
    /// <summary>
    /// Tells whther or not the context has been initialized properly
    /// </summary>
    public static bool Initialized
    {
      get { return sInitialContext != null; }
    }
    /// <summary>
    /// Returns the static default context defined by the basic config file 
    /// </summary>
    /// <returns></returns>
    public static INamingContext GetContext()
    {
      return GetContext(null);
    }
    /// <summary>
    /// Returns a subcontext contained in the master static context or 
    /// the default context if a name is not provided.
    /// Can be a local or remote context.
    /// </summary>
    /// <param name="name">the name of the context as identified in 
    /// the subcontext tag of the ONDI config file</param>
    /// <returns></returns>
    public static INamingContext GetContext(string name)
    {
      StaticInit();
      if(name == null)
      {
        return StaticContext.DefaultContext;
      }
      else
      {
        return StaticContext.mySubContexts[name];
      }
    }
    /// <summary>
    /// 
    /// </summary>
    protected void CheckBindingTable()
    {
      if (myBindingTable == null)
      {
        myBindingTable = new BindingTable();
      }
    }
    /// <summary>
    /// Parses a component configuration based out of this context
    /// </summary>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public ComponentConfiguration ParseComponentConfiguration(string fileName)
    {
      ComponentConfiguration conf = ComponentConfigurationParser.ParseComponentConfiguration(fileName);
      if(conf != null && StringUtils.Contains(conf.ComponentType.AssemblyName, @"${"))
      {
        conf.ComponentType.AssemblyName = (string)ContextValueParser.GetStringDefinedObject(this.Environment, this, conf.ComponentType.AssemblyName, Type.GetType("System.String"));
      }
      return conf;
    }

    private void RegisterRemotingContextMonitor()
    {
      this.Log("Registering RemotingContextMonitor ...",null, LogLevel.Information);
      Type t = typeof(RemotingContextMonitor);
      WellKnownServiceTypeEntry entry = 
                    new WellKnownServiceTypeEntry(
                            t.FullName, 
                            t.Assembly.FullName,
                            CONTEXT_REMOTING_MONITOR_NAME,
                            WellKnownObjectMode.Singleton);

      RemotingConfiguration.RegisterWellKnownServiceType(entry);
    }

    private void RegisterRemoteComponents(DirectoryInfo sourceDir)
    {
      FileInfo[] files = sourceDir.GetFiles();
      foreach(FileInfo file in files)
      {
        string componentName = StringUtils.BackToForwardSlash( file.FullName);
        if(componentName.EndsWith(NamingContextConstants.CONFIG_EXTENSION))
        {
          ComponentConfiguration conf = ParseComponentConfiguration(file.FullName);
          if(conf != null && conf.Remoting != null)
          {
            componentName = StringUtils.Delete(componentName, NamingContextConstants.CONFIG_EXTENSION);
            componentName = StringUtils.Delete(componentName, StringUtils.BackToForwardSlash(this.ContextRootDirectory) + CompositeNameParser.NAME_DELIMITER);
            try
            {
              System.Reflection.Assembly a = System.Reflection.Assembly.Load(conf.ComponentType.AssemblyName);
              if(a != null)
              {
                Type compType = a.GetType(conf.ComponentType.ClassName);
                Type mbrft = typeof(MarshalByRefObject);
                if(compType != null && mbrft.IsAssignableFrom( compType))
                {
                  if(conf.Remoting.ObjectMode.ToLower().Equals("singleton"))
                  {
                    
                    WellKnownServiceTypeEntry entry = 
                                      new WellKnownServiceTypeEntry(
                                                compType.FullName, 
                                                compType.Assembly.FullName,
                                                componentName,
                                                WellKnownObjectMode.Singleton);
                    this.RegisterRemoteEntry(entry, componentName, conf);
                    this.Log("Registered remoting object " + componentName + " as a Singleton object",null,LogLevel.Information);
                  }
                  else if(conf.Remoting.ObjectMode.ToLower().Equals("singlecall"))
                  {
                    WellKnownServiceTypeEntry entry = 
                      new WellKnownServiceTypeEntry(
                      compType.FullName, 
                      compType.Assembly.FullName,
                      componentName,
                      WellKnownObjectMode.SingleCall);
                    this.RegisterRemoteEntry(entry, componentName, conf);
                    this.Log("Registered remoting object " + componentName + " as a SingleCall object",null,LogLevel.Information);
                  }
                  else
                  {
                    this.Log("Could not Register remoting object " + componentName + " because object mode " + conf.Remoting.ObjectMode + " is not a valid mode",null,LogLevel.Warning);
                  }
                }
                else
                {
                  this.Log("Could not Register remoting object " + componentName + " because object type " + compType + " is either null or not assignable to MarshalByRefObject",null,LogLevel.Warning);
                }
              }
            }
            catch(Exception re)
            {
              this.Log("Could not Register remoting object " + componentName + " an exception was caught",re,LogLevel.Error);
            }
          }
        }
      }
      DirectoryInfo[] dirs = sourceDir.GetDirectories();
      foreach(DirectoryInfo dir in dirs)
      {
        this.RegisterRemoteComponents(dir);
      }
    }
    private void RegisterRemoteEntry(WellKnownServiceTypeEntry entry, string componentName, ComponentConfiguration conf)
    {      
      RemotingConfiguration.RegisterWellKnownServiceType(entry);
      //Adding configuration values to remoting object 01/25/2007
      object ctxObj = this.Lookup(componentName);
      if (ctxObj != null)
      {
        if (conf != null)
        {
          try
          {
            string name = componentName;
            string rlink = this.RemotingLinkName;
            if (rlink != null)
            {
              if (!name.StartsWith(CompositeNameParser.NAME_DELIMITER))
              {
                name = CompositeNameParser.NAME_DELIMITER + name;
              }
              name = rlink + name;
            }
            Assembly a = Assembly.Load(conf.ComponentType.AssemblyName);
            Type t = a.GetType(conf.ComponentType.ClassName);
            object remoteObj = Activator.GetObject(t, name);
            if (conf.Properties != null && conf.Properties.Count > 0)
            {
              foreach (ComponentInitializer prop in conf.Properties)
              {
                PropertyInfo propInfo = t.GetProperty(prop.Name);
                object ctxObjPropVal = propInfo.GetValue(ctxObj, null);
                propInfo.SetValue(remoteObj, ctxObjPropVal, null);
              }
            }

          }
          catch (Exception re)
          {
            this.Log("Could not initialize remoting resource named " + componentName + " in context, due to reflection or activation problems", re, LogLevel.Error);
            throw re;
          }
        }
      }
      if(mRegisteredRemotingServices == null)
      {
        mRegisteredRemotingServices = new Hashtable();
      }
      mRegisteredRemotingServices.Add(componentName,conf);
    }
    #region INamingContext Members
    /// <summary>
    /// Implementation of lookup
    /// </summary>
    /// <param name="pName"></param>
    /// <returns></returns>
    public object Lookup(IName pName)
    {
      CheckBindingTable();
      if (pName != null)
      {
        Binding b = myBindingTable[pName.ToString()];
        if (b != null)
        {
          return b.Object;
        }
        else
        {
          lock(m_mutex)
          {
            //Once again check in case another thread created it.
            Binding bLocked = myBindingTable[pName.ToString()];
            if (bLocked != null)
            {
              return bLocked.Object;
            }
            else
            {
              if(!this.AddToInProcess(pName.ToString()))
              {
                throw new CircularReferenceException("Circular reference constraint violated while doing lookup on " + pName.ToString());
              }
              object objInst = null;
              try
              {
                objInst = NamingManager.GetObjectInstance(null, pName, this, this.Environment);
              }
              catch(Exception e)
              {
                this.Log("InitialContext threw exception while doing lookup on object named " + pName.ToString(), e, LogLevel.Error);
                throw e;
              }
              finally
              {
                if(objInst != null)
                {
                  this.Bind(pName, objInst);
                }
                this.RemoveFromInProcess(pName.ToString());
                this.ResolveRemainingReferences();
              }
              return objInst;
            }
          }

        }
      }
      return null;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="pName"></param>
    /// <returns></returns>
    public object Lookup(string pName)
    {
      if(StringUtils.Contains(pName, CompositeNameParser.SECTION_DELIMITER) )
      {
        return LookupLink(pName);
      }
      else
      {
        CompositeNameParser np = new CompositeNameParser();
        return Lookup(np.Parse(pName));
      }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public object LookupLink(IName name)
    {
      System.Text.StringBuilder linkName = new System.Text.StringBuilder();
      string rlink = this.RemoteLinkName;
      if(rlink != null)
      {
        linkName.Append(rlink);
        string compName = name.ToString();
        if(!compName.StartsWith(CompositeNameParser.NAME_DELIMITER))
        {
          compName = CompositeNameParser.NAME_DELIMITER + compName;
        }
        linkName.Append(compName);
        return LookupLink(linkName.ToString());
      }
      return null;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public object LookupLink(string name)
    {
      if(!StringUtils.Contains(name, CompositeNameParser.SECTION_DELIMITER))
      {
        string rlink = this.RemoteLinkName;
        if(rlink != null)
        {
          if(!name.StartsWith(CompositeNameParser.NAME_DELIMITER))
          {
            name = CompositeNameParser.NAME_DELIMITER + name;
          }
          name = rlink + name;
        }
      }
      if(StringUtils.Contains(name, CompositeNameParser.SECTION_DELIMITER))
      {        
        string postfix = name.Substring(name.LastIndexOf(CompositeNameParser.SECTION_DELIMITER) + 1);
        postfix = postfix.Substring(postfix.IndexOf(CompositeNameParser.NAME_DELIMITER));
        string compLocation = StringUtils.ForwardToBackSlash(postfix);
        compLocation = this.ContextRootDirectory + compLocation + NamingContextConstants.CONFIG_EXTENSION;
        ComponentConfiguration conf = this.ParseComponentConfiguration(compLocation);
        if(conf != null)
        {
          try
          {
            System.Reflection.Assembly a = System.Reflection.Assembly.Load(conf.ComponentType.AssemblyName);
            
            return Activator.GetObject(a.GetType(conf.ComponentType.ClassName), name);
          }
          catch(Exception re)
          {
            this.Log("Could not load resource named " + name + " in context, due to reflection or activation problems",re,LogLevel.Error);
            return null;

          }
        }
        else
        {
          this.Log("Could not locate resource named " + name + " in context, No Configuration File Found",null,LogLevel.Error);
          return null;
        }
      }
      this.Log("Could not locate resource named " + name + " in context, Invalid Name",null,LogLevel.Error);
      return null;
    }
    /// <summary>
    /// Implementation of <see cref="INamingContext.GetSubcontext(IName)"/>.
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public INamingContext GetSubcontext(IName name)
    {
      if (this.mySubContexts != null && this.mySubContexts.Contains(name.ToString()))
      {
        return this.mySubContexts[name.ToString()];
      }
      return null;
    }
    /// <summary>
    /// Implementation of <see cref="INamingContext.GetSubcontext(string)"/>.
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public INamingContext GetSubcontext(string name)
    {
      CompositeNameParser np = new CompositeNameParser();
      return this.GetSubcontext(np.Parse(name));
    }
    /// <summary>
    /// Implementation of <see cref="INamingContext.GetSubcontext()"/>.
    /// </summary>
    /// <returns></returns>
    public INamingContext GetSubcontext()
    {
      return this.GetSubcontext("initial");
    }
    /// <summary>
    /// Adds a new environment property to the environment of this context. 
    /// If the property already exists, its value is overwritten. See class 
    /// description for more details on environment properties.
    /// </summary>
    /// <param name="propName">the name of the environment property to add; may not be null</param>
    /// <param name="propVal">the value of the property to add; may not be null</param>
    /// <returns>the previous value of the property, or null if the property was not in the environment before</returns>
    /// <exception cref="NamingException">If some naming action fails</exception>
    public object AddToEnvironment(string propName, object propVal)
    {
      if(string.IsNullOrEmpty(propName))
      {
        throw new NamingException("Attempting to add a property with an empty name to the environment");
      }
      lock(m_mutex)
      {
        if(myProps == null)
        {
          myProps = new Hashtable();
        }
        object current = null;
        if(myProps.ContainsKey(propName))
        {
          current = myProps[propName];
          myProps.Remove(propName);
        }      
        myProps.Add(propName, propVal);
        return current;
      }
    }
    /// <summary>
    /// Removes an environment property from the environment of this context. 
    /// See class description for more details on environment properties
    /// </summary>
    /// <param name="propName">the name of the environment property to remove; may not be null</param>
    /// <returns>the previous value of the property, or null if the property was not in the environment</returns>
    /// <exception cref="NamingException">If some naming action fails</exception>
    public object RemoveFromEnvironment(string propName)
    {
      if(string.IsNullOrEmpty(propName))
      {
        throw new NamingException("Attempting to remove a property with an empty name to the environment");
      }
      object current = null;
      if(myProps != null)
      {
        lock(m_mutex)
        {
          if(myProps.ContainsKey(propName))
          {
            current = myProps[propName];
          }
          myProps.Remove(propName);
        }
      }
      return current;
    }
    /// <summary>
    /// Retrieves the environment in effect for this context. See class description for more details on environment properties. 
    /// <br/><br/>The caller should not make any changes to the object returned: their effect on the context is undefined. 
    /// The environment of this context may be changed using AddToEnvironment() and RemoveFromEnvironment().
    /// </summary>
    public Hashtable Environment
    {
      get { return myProps; }
    }
    /// <summary>
    /// The root directory of this context
    /// </summary>
    public string ContextRootDirectory
    {
      get { return (string) myProps[LOCAL_CONTEXT_ROOT]; }
    }
    /// <summary>
    /// 
    /// </summary>
    public string NameInNamespace
    {
      get
      {
        // TODO:  Add InitialContext.NameInNamespace getter implementation
        return null;
      }
    }
    /// <summary>
    /// Binds a name to an object. All intermediate contexts and the target context 
    /// (that named by all but terminal atomic component of the name) must already exist
    /// </summary>
    /// <param name="name">the name to bind; may not be empty</param>
    /// <param name="obj">the object to bind; possibly null</param>
    public void Bind(IName name, object obj)
    {
      if(name == null || name.GetAll().Count == 0)
      {
        throw new NamingException("Attempting to bind an object with an empty name");
      }
      Bind(name.ToString(), obj);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name">the name to bind; may not be empty</param>
    /// <param name="obj">the object to bind; possibly null</param>
    public void Bind(string name, object obj)
    {
      if(string.IsNullOrEmpty(name))
      {
        throw new NamingException("Attempting to bind an object with an empty name");
      }
      Type type = obj.GetType();
      Binding binding = new Binding(name, type.FullName, type.Assembly.FullName, obj);
      CheckBindingTable();
      
      myBindingTable.Add(name, binding);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <param name="obj"></param>
    public void ReBind(IName name, object obj)
    {
      Bind(name, obj);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <param name="obj"></param>
    public void ReBind(string name, object obj)
    {
      Bind(name, obj);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    public void UnBind(IName name)
    {
      UnBind(name.ToString());
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    public void UnBind(string name)
    {
      if(string.IsNullOrEmpty(name))
      {
        throw new NamingException("Attempting to unbind an object with an empty name");
      }
      CheckBindingTable();
      
      myBindingTable.Remove(name);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="oldName"></param>
    /// <param name="newName"></param>
    public void Rename(IName oldName, IName newName)
    {
      Rename(oldName.ToString(), newName.ToString());
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="oldName"></param>
    /// <param name="newName"></param>
    public void Rename(string oldName, string newName)
    {
      if(string.IsNullOrEmpty(oldName) || string.IsNullOrEmpty(newName))
      {
        throw new NamingException("Attempting to rename an object with an empty name");
      }
      CheckBindingTable();
      object obj = null;
      if(myBindingTable.Contains(oldName))
      {
        obj = myBindingTable[oldName];
        UnBind(oldName);
      }
      Bind(newName, obj);
    }
    /// <summary>
    /// 
    /// </summary>
    public void Close()
    {
      // TODO:  Add InitialContext.Close implementation
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <param name="prefix"></param>
    /// <returns></returns>
    public IName ComposeName(IName name, IName prefix)
    {
      return name.AddAll(0,prefix);
    }
    /// <summary>
    /// Creates a name of type <see cref="CompositeName"/> and returns the ToString method
    /// </summary>
    /// <param name="name"></param>
    /// <param name="prefix"></param>
    /// <returns></returns>
    public string ComposeName(string name, string prefix)
    {
      CompositeName nameOrig = new CompositeName(name);
      return nameOrig.AddAll(0, new CompositeName(prefix)).ToString();
    }
    /// <summary>
    /// This methods creates asubcontext and places it in the sub context table
    /// if a subcontext is already present with the given key, it is blown away 
    /// and reassigned with the newly created context, thus all objects previously 
    /// present in that context will be garbage collected as well.
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public INamingContext CreateSubcontext(IName name)
    {
      INamingContext ctx = null;
      Hashtable initialParam = new Hashtable();
      initialParam.Add(NamingContextConstants.INITIAL_CONTEXT_FACTORY, myProps[NamingContextConstants.INITIAL_CONTEXT_FACTORY]);
      initialParam.Add(NamingContextConstants.INITIAL_CONTEXT_FACTORY_ASSEMBLY, myProps[NamingContextConstants.INITIAL_CONTEXT_FACTORY_ASSEMBLY]);

      object o = this.Lookup(name);
      if (o != null && o is SubContextConfiguration)
      {
        initialParam.Add(CONTEXT_SETTINGS_KEY_NAME, ((SubContextConfiguration)o).ConfigurationFile);
        if (StringUtils.NotEmpty(((SubContextConfiguration)o).FactoryClass))
        {
          initialParam[NamingContextConstants.INITIAL_CONTEXT_FACTORY] = ((SubContextConfiguration)o).FactoryClass;
        }
        if (StringUtils.NotEmpty(((SubContextConfiguration)o).FactoryAssembly))
        {
          initialParam[NamingContextConstants.INITIAL_CONTEXT_FACTORY_ASSEMBLY] = ((SubContextConfiguration)o).FactoryAssembly;
        }
      }
      ctx = NamingManager.GetInitialContext(initialParam);
      if (ctx != null)
      {
        if (this.mySubContexts == null)
        {
          this.mySubContexts = new ContextTable();
        }
        if(this.mySubContexts.Contains(name.ToString()))
        {
          this.mySubContexts[name.ToString()] = ctx;
          this.Log("Successfull (overriden) initialization of subcontext named " + name ,null,LogLevel.Debug);
        }
        else
        {
          this.mySubContexts.Add(name.ToString(), ctx);
          this.Log("Successfull initialization of subcontext named " + name ,null,LogLevel.Debug);                
        }
      }
      return ctx;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public INamingContext CreateSubcontext(string name)
    {
      CompositeNameParser np = new CompositeNameParser();
      return CreateSubcontext(np.Parse(name));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    public void DestroySubcontext(IName name)
    {
      mySubContexts.Remove(name.ToString());
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    public void DestroySubcontext(string name)
    {
      CompositeNameParser np = new CompositeNameParser();
      DestroySubcontext(np.Parse(name));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public INameParser GetNameParser(IName name)
    {
      return new CompositeNameParser();
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public INameParser GetNameParser(string name)
    {
      return new CompositeNameParser();
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public IEnumerator List(IName name)
    {
      // TODO:  Add InitialContext.List implementation
      return null;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public IEnumerator List(string name)
    {
      // TODO:  Add InitialContext.SList implementation
      return null;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public IEnumerator ListBindings(IName name)
    {
      // TODO:  Add InitialContext.ListBindings implementation
      return null;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public IEnumerator ListBindings(string name)
    {
      // TODO:  Add InitialContext.SListBindings implementation
      return null;
    }

    #endregion

    #region IDisposable Members
    private bool mDisposed = false;
    /// <summary>
    /// Disposes resources like remoting ports and subcontexts
    /// </summary>
    public void Dispose()
    {
      if(!mDisposed)
      {
        Dispose(true);
        GC.SuppressFinalize(this);
      }
    }
    /// <summary>
    /// Disposes resources like remoting ports and subcontexts
    /// </summary>
    /// <param name="disposing">flag for disposing time actions</param>
    public void Dispose(bool disposing)
    {
      this.Log("Called InitialContext.Dispose! Disposing context resources....", null, LogLevel.Information);
      if(this.RemotingServerChannel != null)
      {
        this.RemotingServerChannel.StopListening(null);
        try
        {
          ChannelServices.UnregisterChannel(this.RemotingServerChannel);
        }
        catch(Exception e)
        {
          this.Log("A non critical exception was thrown while attempting to unregister channel " + this.RemotingServerChannel.ChannelName + " with remoting services", e, LogLevel.Information);
        }
      }
      if(this.RemotingClientChannel != null)
      {
        try
        {
          ChannelServices.UnregisterChannel(this.RemotingClientChannel);
        }
        catch(Exception e)
        {
          this.Log("A non critical exception was thrown while attempting to unregister channel " + this.RemotingClientChannel.ChannelName + " with remoting services", e, LogLevel.Information);
        }
      }
      if(this.mySubContexts != null)
      {
        foreach(INamingContext subCtx in mySubContexts.Values)
        {
          if(subCtx is IDisposable)
          {
            ((IDisposable)subCtx).Dispose();
          }
        }
      }
      mDisposed = true;
    }

    #endregion
  }
}
